namespace ChumChase.Services
{
    using System;
    using System.IO;
    using System.IO.IsolatedStorage;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;

    [Serializable]
    public class LocalStorage : ILocalStorage
    {
        public void Save(object objectToStore, string fileName)
        {
            using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForAssembly())
            using (var stream = new IsolatedStorageFileStream(fileName, FileMode.OpenOrCreate, file))
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(stream, objectToStore);
            }
        }

        public T Load<T>(string fileName) where T : class
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly())
            {
                string[] fileNames = store.GetFileNames(fileName);

                if (fileNames.Length == 1)
                {
                    try
                    {
                        using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, store))
                        {
                            var formatter = new BinaryFormatter {Binder = new SerializationBinder<T>()};
                            object obj = formatter.Deserialize(stream);
                            return (T) obj;
                        }
                    }
                    catch
                    {
                        // TODO: log the exception.
                        // This is most likely to happen when the class is changed.
                    }
                }

                return null;
            }
        }

        public bool Exists(string fileName)
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForAssembly())
            {
                string[] fileNames = store.GetFileNames(fileName);
                return (fileNames.Length == 1);
            }
        }

        #region Nested type: SerializationBinder

        internal class SerializationBinder<T> : SerializationBinder
        {
            public override Type BindToType(string assemblyName, string typeName)
            {
                Type type = typeof (T);
                return type;
            }
        }

        #endregion
    }
}